#ifndef __MATRIZ__
#define __MATRIZ__
#include <cassert>
#include <iostream>
#include <cstdlib>
#include <math.h>
using namespace std;

class Matriz {
    public:

    /**
     * Constructores
     */
    Matriz();
    Matriz(const unsigned int, const unsigned int);
	Matriz(const unsigned int, const unsigned int, const unsigned int);
	Matriz(const Matriz&);
    ~Matriz();
    
    /**
     *operadores
     */
	
	
	/** deja en este parametro la suma de este con el otro */
    Matriz suma(const Matriz&);
    /** deja en este parametro la resta de este con el otro */
    Matriz resta(const Matriz&);
    /** devuelve el vector de largo dim del resultado de la multiplicacion*/
    Matriz producto(Matriz& m1);
    Matriz producto2(Matriz& m1);
    void productoGivens(Matriz& m1, int i, int j, Matriz& res);
    /** deja en esta matriz el resultado del producto por un escalar*/
    Matriz producto(const double);
    Matriz division(const double);
    /** Pongo los nombres de las var xq es mas delcarativo en este caso
        lo que hace es calcualr Ax=b modificando x y devuelve true si pudo */
    bool resolver(double* b, double* x);
	Matriz triangular(double* be);
	Matriz triangular();
	bool getLU(Matriz& L, Matriz& U);
	bool SOR(int n, Matriz A, float* b, float* X, float w, float tol, int iterMax, float* res);

    Matriz getKAutovectores(Matriz A, unsigned int k, unsigned int alpha, double tolerancia);

    friend Matriz operator+(const Matriz&, const Matriz&);
    friend Matriz operator-(const Matriz&, const Matriz&);
    friend Matriz operator*(const Matriz&, const Matriz&);
    friend Matriz operator*(const double&, const Matriz&);
    friend Matriz operator*(const Matriz&, const double&);


	double interrumpeMetodoQR();
	int identidad();
	int factQR(Matriz& Q, Matriz& R, double alpha);
	Matriz trasponer();
	double norm(pair<double,double> x);
	double absDouble(double);
	void copiarDiagonal(Matriz a);
	void valChicosPonemosCero(double tolerancia);
	bool esDiagonal();

    /**
     * getters
     */

    /** devuelve un id unico corresdiente a la posicion del elemento en la matriz */
    double getId(unsigned int, unsigned int) const;
    double operator()(unsigned int, unsigned int) const;
    double operator()(unsigned int) const;
    unsigned int size() const;

    /**
     * setters
     */
    void setPos(unsigned int, unsigned int, double);
    void setPosCampoN(unsigned int, unsigned int, double*);
    void setPosInId(unsigned int, double);

    /**
     * comparaciones y asignacion
     */
    bool operator==(const Matriz&) const;
    bool operator!=(const Matriz&) const;
   void operator=(const Matriz&);
	friend ostream& operator<<(ostream& out, const Matriz& m);

    unsigned int dim;
    unsigned int n;
    unsigned int m;
    private:
    double * matriz;

    void swapRows(unsigned int i, unsigned int j);
};


#endif
